                                               /* In his Name */

#ifndef __STRASSEN_TASK_H_
#define __STRASSEN_TASK_H_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "Matrix_util.h"
#include "TFrame.h"
#include "util.h"


#define MY_THRESHOLD 64 

class M1_Task: public Task {
 private:
  float* _a11,* _a22,* _b11,* _b22;
  int _half;
  float* atemp, * btemp;
  TState* _pState;
  WorkQueue * _Q;

 public: 
  // return matrix
  float* _M1;

  // Constructor
  M1_Task(float* a11,float* a22, float* b11, float* b22,float* M1, int half,TState* pState, WorkQueue * Q);

  // destructor
  ~M1_Task();

  // Work function 
  virtual void run();

  // Print function 
  virtual void print();
};

/* M2 Task */

class M2_Task: public Task {
 private:
  float* _a21,* _a22,* _b11;
  int _half;
  float* atemp, * btemp;
  TState* _pState;
  WorkQueue * _Q;

 public: 
  // return matrix
  float* _M2;
  // Constructor
  M2_Task(float* a21,float* a22, float* b11,float* M2, int half,TState* pState, WorkQueue * Q);

  // destructor
  ~M2_Task();

  // Work function 
  virtual void run();

  // Print function 
  virtual void print();
};
/* End of M2 Task */

/* M3 Task */

class M3_Task : public Task {
 private:
  float* _a11,* _b12, *_b21;
  int _half;
  float * atemp;
  TState* _pState;
  WorkQueue * _Q;

 public:
  // return matrix
  float* _M3;

  // task constructor
  M3_Task(float* a11, float* b12, float* b21,float *M3, int half,TState* pState,  WorkQueue * Q);

  // destructor 
  ~M3_Task();

  // run function 
  virtual void run();

  // Print function 
  virtual void print();
};

/* End of M3 Task */

/* M4 Task */
class M4_Task : public Task {
 private:
  float* _a22, * _b21, * _b11;
  int _half;
  float * atemp;
  TState* _pState;
  WorkQueue * _Q;
 public:
  // return matrix
  float * _M4;

  // cosntructor
  M4_Task(float* a22, float* b21, float* b11, float* M4, int half,TState* pState, WorkQueue * Q);

  // destructor
  ~M4_Task();

  // run function
  virtual void run();

  // Print function 
  virtual void print();
};

/* End of M4 Task */

/* M5 Task */

class M5_Task : public Task {
 private:
  float* _a11, * _a12, * _b22;
  int _half;
  float * atemp;
  TState* _pState;
  WorkQueue * _Q;

 public:
  // return matrix
  float * _M5;

  // cosntructor
  M5_Task(float* a11,float* a12,  float* b22, float* M5, int half,TState* pState, WorkQueue * Q);

  // destructor
  ~M5_Task();

  // run function
  virtual void run();

  // Print function 
  virtual void print();
};

/* End of M5 Task */

/* M6 Task */

class M6_Task: public Task {
 private:
  float* _a21,* _a11,* _b11,* _b12;
  int _half;
  float* atemp, * btemp;
  TState* _pState;
  WorkQueue * _Q;

 public: 
  // return matrix
  float* _M6;

  // Constructor
  M6_Task(float* a21,float* a11, float* b11, float* b12,float* M6, int half,TState* pState,  WorkQueue * Q);

  // destructor
  ~M6_Task();

  // Work function 
  virtual void run();

  // Print function 
  virtual void print();
};

/* End of M6 Task */

/* M7 Task */

class M7_Task: public Task {
 private:
  float* _a12,* _a22,* _b21,* _b22;
  int _half;
  float* atemp, * btemp;
  TState* _pState;
  WorkQueue * _Q;

 public: 
  // return matrix
  float* _M7;

  // Constructor
  M7_Task(float* a12,float* a22, float* b21, float* b22,float* M7, int half,TState* pState,  WorkQueue * Q);

  // destructor
  ~M7_Task();

  // Work function 
  virtual void run();

  // Print function 
  virtual void print();
};

/* End of M7 Task */

// Class that implements the main strassen function 
class Strassen : public Task {
  /* 
   *This task must be able to spawn seven smaller tasks and must 
   * keep track of the state of each one using the state enum. 
   * When all tasks are idle, it starts itself. When all tasks are 
   * working it must put itself to sleep. When all tasks are done, 
   * it must continue its work based on the returned results. 
   */
 public:
  bool starting;
  int half;
  float* a11,* a12,* a21,* a22,
    * b11,* b12,* b21,* b22,
    * c11,* c12,* c21,* c22,
    * M1,* M2,* M3,* M4,* M5,* M6,* M7,
    * atemp, * btemp, * _a, * _b, * _c;
  TState * _pState;
  TState * myState;
  int mysize;
  WorkQueue * Q;
  int sid; 
  Strassen(float* a, float *b, float* c, int size, WorkQueue *  _Q , TState * pState , int _sid );
  
  ~Strassen();
  
  virtual void run();

  // Print function 
  virtual void print();

};

#endif
